package com.dq.service.messsge.impl;

import com.dq.exception.customException.AdminException;
import com.dq.controller.in.MessageQuery;
import com.dq.domain.message.oneself.InstructionMessage;
import com.dq.domain.message.oneself.Message;
import com.dq.domain.message.oneself.centre.ApprovalUserCentre;
import com.dq.domain.message.oneself.centre.InstructionStaffuserCentre;
import com.dq.domain.sys.user.user.BossUser;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.repository.BaseRepositories;
import com.dq.service.messsge.MessageService;
import com.dq.service.sys.user.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author cf
 *
 */
@Service
public class MessageServiceImpl extends BaseRepositories implements MessageService {
    @Autowired
    private SysUserService sysUserService;


    /**
     * 查看
     * @param id
     * @return
     * @throws AdminException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void look(Long id, String type) throws AdminException {
        SysUser user = sysUserService.getUser();
        if(Message.MessageType.approval.toString().equals(type)) {
            // 采购
            ApprovalUserCentre approvalUserCentre = dao.get(ApprovalUserCentre.class, id);
            if(approvalUserCentre == null) {
                throw new AdminException("无对应id对象");
            }
            approvalUserCentre.setMessageStatus(Message.MessageStatus.alreadySee);
            approvalUserCentre.setLastModifyTime(System.currentTimeMillis());
            approvalUserCentre.setUpdateUser(user);
            dao.modify(approvalUserCentre);
        }else if(Message.MessageType.instruction.toString().equals(type)) {
            // 指令
            InstructionMessage instructionMessage = dao.get(InstructionMessage.class, id);
            if(instructionMessage == null) {
                throw new AdminException("无对应id对象");
            }
            if(user instanceof BossUser) {
                instructionMessage.setMessageStatus(Message.MessageStatus.alreadySee);
                instructionMessage.setLastModifyTime(System.currentTimeMillis());
                dao.modify(instructionMessage);
            }else {
                HashMap<String, Object> queryCentre = new HashMap<>(16);
                queryCentre.put("staffUser_id", user.getId());
                queryCentre.put("instructionMessage_id", instructionMessage.getId());
                List<InstructionStaffuserCentre> menuList = dao.find(dao.query2Hql(InstructionStaffuserCentre.class, queryCentre), queryCentre);
                if(menuList == null || menuList.size() <= 0) {
                    throw new AdminException("数据异常，此指令未分配给此员工");
                }else if(menuList.size() > 1) {
                    throw new AdminException("数据异常， 一个指令回复两次");
                }
                InstructionStaffuserCentre instructionStaffuserCentre = menuList.get(0);
                instructionStaffuserCentre.setMessageStatus(Message.MessageStatus.alreadySee);
                instructionStaffuserCentre.setLastModifyTime(System.currentTimeMillis());
                dao.modify(instructionStaffuserCentre);
            }
        }else {
            Message message = dao.get(Message.class, id);
            if (message == null) {
                throw new AdminException("无对应id对象");
            }
            message.setMessageStatus(Message.MessageStatus.alreadySee);
            message.setLastModifyTime(System.currentTimeMillis());

            message.setUpdateUser(user);

            dao.modify(message);
        }
    }

    /**
     * 员工/门店/boss消息查询
     */
    @Override
    public List<Message> messageListSql(String searchType, String theme, List messageTypes, Long userId, Long orgId, Long beginSearchTime, Long endSearchTime, Integer page, Integer pagesize) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT m.* FROM message m ");
        sql = getSql(sql, searchType, userId, orgId);
        // todo 避免 关联子表 出现list数量不匹配
        if(searchType.equals(MessageQuery.Type.boss.toString())) {
            sql.append(" group by m.id");
        }

        // 排序
        sql.append(" order by m.id desc ");

        Map<String, Object> query = new HashMap<>(16);
        query.put("beginSearchTime", beginSearchTime);
        query.put("endSearchTime", endSearchTime);
        query.put("messageTypes", messageTypes);
        query.put("theme", theme);
        query.put("page", page);
        query.put("size", pagesize);
        List<Message> list = dao.findBySql(Message.class, sql.toString(), query);

        return list;
    }
    /**
     * 员工/门店/boss消息查询
     */
    @Override
    public Long messageCountSql(String searchType, String theme, List messageTypes, Long userId, Long orgId, Long beginSearchTime, Long endSearchTime) {
        StringBuilder sql = new StringBuilder();
        if(searchType.equals(MessageQuery.Type.boss.toString())) {
            sql.append("select count(nas.n) from (SELECT count(m.id) n FROM message m ");
        }else {
            sql.append("SELECT count(m.id) FROM message m ");
        }
        sql = getSql(sql, searchType, userId, orgId);
        // todo 避免 关联子表 出现list数量不匹配
        if(searchType.equals(MessageQuery.Type.boss.toString())) {
            sql.append(" group by m.id ) nas");
        }


        Map<String, Object> query = new HashMap<>(16);
        query.put("beginSearchTime", beginSearchTime);
        query.put("endSearchTime", endSearchTime);
        query.put("messageTypes", messageTypes);
        query.put("theme", theme);

        return dao.countBySql(sql.toString(), query);
    }

    /**
     * 员工/门店/boss消息查询
     */
    private StringBuilder getSql(StringBuilder sql, String searchType, Long userId, Long orgId) {
        sql.append("LEFT JOIN instruction_staffuser_centre i ON i.instruction_message_id=m.id ");
        sql.append("LEFT JOIN approval_user_centre a ON a.approval_message_id=m.id ");
        sql.append("LEFT JOIN subscribe s ON s.id=m.subscribe_id ");
        sql.append("where m.deleted = false ");
        sql.append("and if(:beginSearchTime is not null, m.create_time >= :beginSearchTime, 1=1) ");
        sql.append("and if(:endSearchTime is not null, m.create_time < :endSearchTime, 1=1) ");
        sql.append("and m.message_type in :messageTypes ");
        sql.append("and if(:theme is not null, m.theme like :theme, 1=1) ");

        if(searchType.equals(MessageQuery.Type.boss.toString())) {
            String sub = String.format("and ((m.create_user_id = %s and m.dtype = 'NoticeMessage') OR (m.create_user_id = %s and m.dtype = 'InstructionMessage') OR a.case_user_id = %s) ",
                                        userId, userId, userId);
            sql.append(sub);
        }else {
            if(searchType.equals(MessageQuery.Type.org.toString())) {
                String sub = String.format("and ((m.case_user_id = %s and m.user_type = 0 and m.dtype = 'NoticeMessage') OR (m.org_id = %s and m.user_type = 0 and m.dtype = 'SubscribeMessage') " +
                        "OR i.staff_user_id = %s OR (m.create_user_id = %s and m.dtype = 'ApprovalMessage')) ",
                        userId, orgId, userId, userId);
                sql.append(sub);
            }else {
                String sub = String.format(" and ((m.case_user_id = %s and m.user_type = 0 and m.dtype = 'NoticeMessage') OR (m.case_user_id = %s and m.user_type = 0 and m.dtype = 'SubscribeMessage')" +
                        " OR i.staff_user_id = %s OR (m.create_user_id = %s and m.dtype = 'ApprovalMessage')) ", userId, userId, userId, userId);
                sql.append(sub);
            }
        }

        System.out.println(sql.toString());

        return sql;
    }

    /**
     * 顾客 消息查询
     */
    @Override
    public List<Message> messageListSqlApi(String theme, List messageTypes, Long userId, Long beginSearchTime, Long endSearchTime, Integer page, Integer pagesize) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT m.* FROM message m ");
        sql = getSqlApi(sql, userId);

        Map<String, Object> query = new HashMap<>(16);
        query.put("beginSearchTime", beginSearchTime);
        query.put("endSearchTime", endSearchTime);
        query.put("messageTypes", messageTypes);
        query.put("theme", theme);

        query.put("page", page);
        query.put("size", pagesize);
        List<Message> list = dao.findBySql(Message.class, sql.toString(), query);

        return list;
    }
    /**
     * 顾客 消息查询
     */
    @Override
    public Long messageCountSqlApi(String theme, List messageTypes, Long userId, Long beginSearchTime, Long endSearchTime) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT count(m.id) FROM message m ");
        sql = getSqlApi(sql, userId);

        Map<String, Object> query = new HashMap<>(16);
        query.put("beginSearchTime", beginSearchTime);
        query.put("endSearchTime", endSearchTime);
        query.put("messageTypes", messageTypes);
        query.put("theme", theme);

        return dao.countBySql(sql.toString(), query);
    }
    /**
     * 顾客 消息查询
     */
    private StringBuilder getSqlApi(StringBuilder sql, Long userId) {
        sql.append("LEFT JOIN subscribe s ON s.id=m.subscribe_id ");
        sql.append("LEFT JOIN service_record sr ON sr.id=m.service_record_id ");
        sql.append("where m.deleted = false ");
        sql.append("and if(:beginSearchTime is not null, m.create_time >= :beginSearchTime, 1=1) ");
        sql.append("and if(:endSearchTime is not null, m.create_time < :endSearchTime, 1=1) ");
        sql.append("and m.message_type in :messageTypes ");
        sql.append("and if(:theme is not null, m.theme like :theme, 1=1) ");

        String sub = String.format("and ((m.case_user_id = %s and m.user_type = 1 and m.dtype = 'NoticeMessage') " +
                " OR (m.case_user_id = %s and m.user_type = 1 and m.dtype = 'SubscribeMessage') " +
                " OR (m.wxuser_id = %s and m.dtype = 'ServiceMessage') ) ", userId, userId, userId);
        sql.append(sub);
        sql.append(" order by m.id desc");
        System.out.println(sql.toString());

        return sql;
    }

}

